<template>
  <n-card>
    <div class="icon-header-container">
      <n-h2 prefix="bar">
        <n-text type="primary"> 图标库 </n-text>
      </n-h2>
      <n-grid
        :x-gap="22"
        :y-gap="8"
        cols="1 s:2 m:4 l:4 xl:4 2xl:4"
        responsive="screen"
      >
        <n-gi>
          <div class="header-item icon-search">
            <label>图标名称</label>
            <n-input-group>
              <n-input
                :style="{ width: '50%' }"
                @change="handleIconSearch"
                clearable
              />
              <n-button type="primary" ghost> 搜索 </n-button>
            </n-input-group>
          </div>
        </n-gi>
        <n-gi>
          <div class="header-item icon-size">
            <label>图标大小</label>
            <n-input-number
              v-model:value="state.iconConfig.size"
              :min="0"
              :max="200"
              button-placement="both"
            />
          </div>
        </n-gi>
        <n-gi>
          <div class="header-item icon-type">
            <label>图标类型</label>
            <n-select
              v-model:value="state.iconType"
              :options="iconList"
              label-field="type"
              value-field="type"
              @update:value="handleIconTypeChange"
            />
          </div>
        </n-gi>
        <n-gi v-if="state.iconType !== ICON_OPTIONS.SVG_ICON">
          <div class="header-item icon-size">
            <label>多彩图标</label>
            <n-color-picker
              v-model:value="state.iconConfig.fill"
              :swatches="[
                '#FFFFFF',
                '#18A058',
                '#2080F0',
                '#F0A020',
                'rgba(208, 48, 80, 1)'
              ]"
            />
          </div>
        </n-gi>
      </n-grid>
    </div>
    <div class="icon-list-container" v-loading="state.loading">
      <n-grid
        :x-gap="14"
        :y-gap="8"
        cols="5 s:5 m:8 l:12 xl:12 2xl:12"
        responsive="screen"
      >
        <n-gi
          v-for="icon in data.dataList"
          :key="`${icon.name}${icon.title}`"
          @click="handleToClipboard(icon)"
        >
          <n-card hoverable class="icon-card">
            <div
              class="icon-container"
              :class="{ clipboard: state.clipboardShow === icon.name }"
              @mouseenter.stop.prevent="state.clipboardShow = icon.name"
              @mouseleave.stop.prevent="state.clipboardShow = ''"
            >
              <div class="icon">
                <icons
                  v-if="state.iconConfig.fill"
                  :name="icon.name"
                  :size="state.iconConfig.size"
                  :fill="state.iconConfig.fill"
                />
                <icons v-else :name="icon.name" :size="state.iconConfig.size" />
              </div>

              <transition name="slide-fade">
                <div
                  class="icon-clipboard"
                  v-if="state.clipboardShow === icon.name"
                >
                  复制
                </div>
              </transition>
            </div>
          </n-card>
          <div class="icon-title">{{ icon.title }}</div>
        </n-gi>
      </n-grid>
      <n-pagination
        v-model:page="state.pageArg.currentPage"
        v-model:page-size="state.pageArg.pageSize"
        class="list-pagination"
        :item-count="data.total"
        show-size-picker
        :page-sizes="state.pageArg.pageSizes"
      />
    </div>
  </n-card>
</template>
<script lang="ts" setup name="proIconList">
  import iconMap from '@icon-park/vue-next/icons.json'
  import { getIconColor } from '@/hooks'
  import toClipboard from '@/utils/clipboard'
  const svgFiles = import.meta.glob('/src/assets/svg/*.svg')

  enum ICON_OPTIONS {
    ICON_PARK = 'iconPark',
    SVG_ICON = 'svgIcon'
  }

  const defaultPage = {
    currentPage: 1,
    pageSize: 72,
    pageSizes: [
      {
        label: '36 每页',
        value: 36
      },
      {
        label: '72 每页',
        value: 72
      },
      {
        label: '100 每页',
        value: 100
      }
    ]
  }

  const defaultIconConfig = {
    size: 20,
    fill: getIconColor().value,
    name: ''
  }

  const state = reactive({
    pageArg: { ...defaultPage },
    iconType: ICON_OPTIONS.ICON_PARK,
    iconConfig: { ...defaultIconConfig },
    loading: true,
    iconSearch: (v) => v,
    clipboardShow: ''
  })

  const iconPark = {
    type: ICON_OPTIONS.ICON_PARK,
    list: iconMap.map((icon) => ({
      title: icon.title,
      name: `i-${icon.name}`
    })),
    total: iconMap.length
  }

  const svgIcon = {
    type: ICON_OPTIONS.SVG_ICON,
    list: Object.keys(svgFiles).map((icon) => {
      const title = icon.replace('/src/assets/svg/', '').replace(/.svg$/, '')
      return {
        name: `icon-${title}`,
        title
      }
    }),
    total: Object.keys(svgFiles).length
  }

  const iconList = [iconPark, svgIcon]

  const data = computed(() => {
    state.loading = true

    const result = iconList.find((icons) => icons.type === state.iconType)
    const { currentPage, pageSize } = state.pageArg
    const list = state.iconSearch(result?.list || [])

    nextTick(() => {
      state.loading = false
    })

    return list
      ? {
          dataList: list.slice(
            (currentPage - 1) * pageSize,
            currentPage * pageSize
          ),
          total: list.length
        }
      : { dataList: [], total: 0 }
  })

  // 分页重置
  const resetPage = () => {
    Object.assign(state.pageArg, { ...defaultPage })
  }

  // 搜索
  const handleIconSearch = (value) => {
    state.iconSearch = (list) => {
      return list.filter(
        (icon) =>
          new RegExp(value).test(icon.name) ||
          new RegExp(value).test(icon.title)
      )
    }
    resetPage()
  }

  // 类型变化
  const handleIconTypeChange = () => {
    Object.assign(state.iconConfig, {
      ...defaultIconConfig,
      fill: getIconColor().value
    })
    resetPage()
  }

  // 复制功能
  const handleToClipboard = async (icon) => {
    try {
      const { size, fill } = state.iconConfig
      const realFill = fill === getIconColor().value ? null : fill
      const content = `<icons name="${icon.name}" size="${size}" ${
        realFill ? 'fill="' + realFill + '"' : ''
      } />`
      await toClipboard(content)
      window.$message.success(`拷贝${content}成功`)
    } catch (err) {
      console.log(err)
      window.$message.error('拷贝失败')
    }
  }
</script>

<style lang="less" scoped>
  .icon-header-container {
    .header-item {
      display: flex;
      align-items: center;
    }
    label {
      min-width: 70px;
    }

    :deep(.n-input-number) {
      flex: 1;
      .n-input__input {
        text-align: center;
      }
    }
    :deep(.n-input) {
      flex: 1;
    }
  }

  .icon-list-container {
    margin-top: 30px;
    .icon-card {
      cursor: pointer;
    }
    .icon-container {
      text-align: center;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      overflow: hidden;

      .icon {
        margin-bottom: 0px;
        transition: all 0.1s cubic-bezier(1, 0.5, 0.8, 1);
      }
      &.clipboard {
        .icon {
          margin-bottom: 5px;
        }
      }
    }
    .icon-title {
      overflow: hidden;
      font-size: 12px;
      line-height: 30px;
      text-align: center;
      text-overflow: ellipsis;
      white-space: nowrap;
      cursor: pointer;
    }
    .list-pagination {
      margin-top: 30px;
      justify-content: center;
    }
    .icon-clipboard {
      height: 25px;
      line-height: 25px;
      background-color: var(--primary-color);
      color: #fff;
      border-radius: 0 0 6px 6px;
      opacity: 1;
      margin-bottom: -7px;
    }

    .slide-fade-leave-active,
    .slide-fade-enter-active {
      transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1);
    }

    .slide-fade-enter-from,
    .slide-fade-leave-to {
      opacity: 0;
      transform: translate3d(0, 25px, 0);
    }

    :deep(.n-card) {
      height: 60px;
    }

    :deep(.n-card__content) {
      padding: 0px;
    }
  }
</style>
